<template>
<div class="calendar">
  <div class="title">
    <Button type="text" @click="delmonth"><Icon type="ios-arrow-left"></Icon></Button>
    <span>{{moment(currentMonth).format("YYYY年MM月")}}</span>
    <Button type="text" @click="addmonth"><Icon type="ios-arrow-right"></Icon></Button>
    <Button type="text" @click="resetmonth" style="float:right">回当月</Button>
  </div>
  <div class="calendar-table">
    <table>
      <thead>
        <tr>
          <th v-for="(v,i) in 7" :key="`ac-week-th-key-${i}`">{{['一','二','三','四','五','六','日'][i]}}</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="(w,n) in weekday" :key="`ac-month-week-key-${n}`">
          <td v-for="(v,i) in w" :key="`ac-month-day-key-${i}`"
              :class="{'noday':isnoday(v),'nowday':isnowday(v),'hasData':isHasData(v),'selected':isSelected(v),'disabled':isDisabled(v),'range':isRange(v)}"
              @click="selectDay(v)" @mouseover="hoverDay(v)">
            <span>{{v.date()}}</span>
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</div>
</template>
<style lang="less" src="@/assets/styles/calendar.less" scoped></style>

<script>
  import moment from 'moment'

  export default {
    props: {
      value: {
        type: [Date, Array]
      },
      range: {
        type: Boolean,
        default: false
      },
      multiple: {
        type: Boolean,
        default: false
      },
      markers: {
        type: Array,
        default(){
          return [];
        }
      },
      options: {
        type: Object
      },
      month:{type:Date}
    },
    data() {
      return {
        model: this.value,
        currentMonth: this.month||moment().toDate(),
        mft:'YYYY-MM-DD',
        rangetemp: []
      };
    },
    watch: {
      value(v) {
        this.model = v;
      },
      model(v) {
        this.$emit('input', v);
        this.$emit('on-change',v);
        this.$parent.$emit('on-form-change', v);
        if (this.range) this.rangetemp = [...v];
      },
      month(v){
        this.currentMonth = v;
      }
    },
    computed: {
      weekday() {
        let mc = moment(this.currentMonth);
        let weekday = [];
        let days = mc.daysInMonth();
        let start = moment(`${mc.format("YYYY-MM")}-01`);
        let end = moment(`${mc.format("YYYY-MM")}-${days}`);
        let startDay = start.day() || 7;
        let endDay = end.day() || 7;
        if (startDay !== 1) {
          weekday.push([]);
        }
        for (let i = startDay; i > 1; i--) {
          weekday[0].push(moment(start.toDate()).subtract(i - 1, 'd'));
        }
        for (let i = 1; i <= days; i++) {
          let week = weekday[weekday.length - 1];
          if (!week || week.length === 7) {
            week = weekday[weekday.length] = [];
          }
          week.push(moment(`${mc.format("YYYY-MM")}-${i}`, 'YYYY-MM-DD'));
        }
        for (let i = 1; i <= 7 - endDay; i++) {
          weekday[weekday.length - 1].push(moment(end.add(1, 'd').toDate()));
        }
        return weekday;
      }
    },
    methods: {
      moment,
      addmonth(){
        this.currentMonth = moment(this.currentMonth).add(1,'M').toDate();
        this.$emit('change-month',this.currentMonth);
      },
      delmonth(){
        this.currentMonth = moment(this.currentMonth).subtract(1,'M').toDate();
        this.$emit('change-month',this.currentMonth);
      },
      resetmonth(){
        this.currentMonth = moment().toDate();
        this.$emit('change-month',this.currentMonth);
      },
      isnoday(v){
        return v.format('YYYY-MM') !== moment(this.currentMonth).format('YYYY-MM');
      },
      isnowday(v){
        return v.format(this.mft) === moment().format(this.mft);
      },
			isHasData(v){
        let has = this.markers.some(o => moment(o).format(this.mft) === v.format(this.mft));
        return has;
			},
      isSelected(v){
        if (this.multiple || this.range) {
          let has = this.model.some(o => moment(o).format(this.mft) === v.format(this.mft));
          return has;
        } else {
          if (!this.model) return false;
          return moment(this.model).format(this.mft) === v.format(this.mft);
        }
      },
      isDisabled(v){
        let ops = this.options;
        let disabled = ops && ops.disabledDate && typeof ops.disabledDate === 'function' && ops.disabledDate(v.toDate());
        return disabled;
      },
      isRange(v){
        if (this.range && this.rangetemp.length === 2){
          let lst = [...this.rangetemp].sort((a,b) => a - b);
          let d = v.toDate();
          return d >= lst[0] && d <= lst[1];
        }
        return false;
      },
      hoverDay(v){
        if (this.range && this.model.length === 1){
          this.rangetemp[1] = v.toDate();
          this.$forceUpdate();
        }
      },
      selectDay(v){
        if (this.isDisabled(v)) return;
        if (this.range) {
          if (this.model.length === 2) {
            this.model = [];
          }
          this.model.push(v.toDate());
          this.model.sort((a,b) => a - b);
        } else if (this.multiple) {
          let i = this.model.findIndex(o => moment(o).format(this.mft) === v.format(this.mft));
          if (i >= 0) {
            this.model.splice(i,1);
          } else{
            this.model.push(v.toDate());
          }
        } else {
          this.model = v.toDate();
        }
      }
    }
  }
</script>
